//
//  StageScene+Collision.swift
//  MixFruit
//
//  Created by remy on 2021/8/24.
//

extension StageScene: SKPhysicsContactDelegate {
    func didBegin(_ contact: SKPhysicsContact) {
        guard !isGameover else { return }
        let bitmaskA = contact.bodyA.categoryBitMask
        let bitmaskB = contact.bodyB.categoryBitMask
        if bitmaskA == bitmaskB {
            // 相同水果测试碰撞除了西瓜
            guard let nodeA = contact.bodyA.node as? SKSpriteNode, let nodeB = contact.bodyB.node as? SKSpriteNode else { return }
            guard let type = nodeA.userData?["type"] as? FruitBox.FruitType else { return }
            self.run(bombAudio)
            // 水果合成
            self.score += type.score
            if type == .halfwatermelon {
                // 祝贺西瓜合成
                bonus()
                self.run(winAudio)
            }
            let ay = Int(nodeA.position.y)
            let by = Int(nodeB.position.y)
            var (start, end) = (nodeA, nodeB)
            if abs(ay - by) < 3 {
                // 高度相同(允许一定的高度误差,相同精灵水平滚动会出现高度不同),向滚动方向合并
                let rollArrow = nodeA.physicsBody!.velocity.dx + nodeB.physicsBody!.velocity.dx
                if (rollArrow > 0 && nodeA.position.x > nodeB.position.x) || (rollArrow < 0 && nodeA.position.x < nodeB.position.x) {
                    (start, end) = (nodeB, nodeA)
                }
            } else {
                // 优先判断高度,总是向下合并
                if ay < by {
                    (start, end) = (nodeB, nodeA)
                }
            }
            nodeA.physicsBody = nil
            nodeB.physicsBody = nil
            let move = SKAction.move(to: end.position, duration: 0.1)
            move.timingMode = .easeOut
            start.run(move)
            start.run(.fadeOut(withDuration: 0.1)) {
                start.removeFromParent()
                self.fallFruits.removeAll(item: start)
            }
            end.run(.fadeOut(withDuration: 0.1)) {
                end.removeFromParent()
                self.fallFruits.removeAll(item: end)
                self.upgradeFruit(end, end.position)
            }
        } else {
            if bitmaskA | bitmaskB == 0xFF {
                // 水果&地面
                guard let fruitNode = bitmaskA == 0xFF ? contact.bodyB.node : contact.bodyA.node else { return }
                guard fruitNode.userData?["sound"] as? Bool ?? false else { return }
                fruitNode.userData?["sound"] = false
                self.run(falldownAudio)
            }
        }
    }
    
    private func bonus() {
        guard self.childNode(withName: "bonus") == nil else { return }
        let wrap = SKSpriteNode(color: UIColor(0x000000, 0.4), size: UIScreen.size)
        wrap.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
        wrap.name = "bonus"
        self.addChild(wrap)
        let layer = SKNode()
        wrap.addChild(layer)
        let light = SKSpriteNode(imageNamed: "light")
        light.run(.rotate(byAngle: 60.0, duration: 100.0))
        layer.addChild(light)
        let watermelon = SKSpriteNode(imageNamed: FruitBox.FruitType.watermelon.name)
        watermelon.setScale(0.6)
        layer.addChild(watermelon)
        layer.setScale(0.0)
        layer.position = CGPoint(x: 0.0, y: 50.0)
        layer.run(.group([
            .sequence([
                .scale(to: 1.0, duration: 0.7),
                .wait(forDuration: 1.4),
                .scale(to: 0.0, duration: 0.5)
            ]),
            .sequence([
                .moveTo(y: 150.0, duration: 0.3),
                .moveTo(y: 0.0, duration: 0.4),
                .wait(forDuration: 1.4),
                .moveTo(y: 500.0, duration: 0.5),
                .run {
                    wrap.run(.sequence([
                        .fadeOut(withDuration: 0.1),
                        .removeFromParent()
                    ]))
                }
            ])
        ]))
    }
    
    private func upgradeFruit(_ node: SKSpriteNode, _ position: CGPoint) {
        guard let type = node.userData?["type"] as? FruitBox.FruitType else { return }
        let upgradeType = FruitBox.FruitType(rawValue: type.rawValue + 1)!
        let newNode = fruitBox.makeFruit(upgradeType)
        newNode.position = position
        newNode.userData?["sound"] = false
        self.fruitWrap.addChild(newNode)
        self.fallFruits.append(newNode)
        newNode.setScale(0.0)
        newNode.run(.scale(to: 1.0, duration: TIME_APPEAR)) {
            self.fruitBox.physicsFruit(newNode)
        }
    }
}
